﻿using System;
using System.Collections.Generic;
using Grishko.DataTier;
using Grishko.SerilizeTools;
using Grishko.DataTier.SqlLibrary;
using OutdoorLib.Context;

using OutdoorLib.BaseEntity.WS;
using OutdoorLib.BaseEntity.Agency;
using OutdoorLib.BaseEntity.Dictionary;
using OutdoorLib.BaseEntity.Face;
using OutdoorLib.BaseEntity.Constraction;
using System.ComponentModel;
using Ecopsy.Tools;


namespace OutdoorLib.BaseEntity.Contract



{
    /// <summary>
    /// Описание контракта
    /// </summary>
    
    [TagNameInfo(TagName = "Contract")]
    public class ContractEntity : SqlAgencyEntity
    {
                
        public override string ID
        {
            get
            {
                return base.ID;
            }
            set
            {
                base.ID = value;
                
            }
        }
        
        /// <summary>
        /// Номер контракта
        /// </summary>
        [SrchItemInfo(TxtPropertyName = "Номер")]
        public string Number
        {
            get;
            set;
        }

        [SrchItemInfo(TxtPropertyName = "Клиент")]
        public Client Client { get; set; }
        /// <summary>
        /// Дата начала контракта = дате начала по первой поверхности - если поверхностей нет - первый день текущего месяца
        /// </summary>        
        [SrchItemInfo(TxtPropertyName = "Дата начала")]
        public DateTime StartDate
        {
            get
            {
                return DateTime.Now;                
                
            }
        }

        /// <summary>
        /// Дата начала контракта = дате окончания по второй поверхности - если поверхностей нет - последний день текущего месяца
        /// </summary>
        [SrchItemInfo(TxtPropertyName = "Дата окончания")]
        public DateTime EndDate
        {
            get
            {
                return DateTime.Now;
              //  return ContractSurfaceItemList.GetMaxEndDate() ;
            }         
        }

        [SrchItemInfo(TxtPropertyName = "Финансы")]
        public TFinanceInfo FinanceInfo { get; set; }
        
        [SrchItemInfo(TxtPropertyName = "Статус")]
        public TContractStatus ContractStatus
        {
            get;
            set;
        }

        private TContractSideItemList _ContractSide =new TContractSideItemList ();

        public TContractSideItemList ContractSideItemList
        {
            get { _ContractSide.Owner = this;
                return _ContractSide; }
            set { _ContractSide = value; }
        }

        /// <summary>
        /// виртуальное свойство
        /// </summary>
        [SrchItemInfo(TxtPropertyName = "Конструкция")]
        public ConstractionEntity Constraction
        { get; set; }

        
        #region Методы
        private static DateTime GetMinMax(ContractSurfaceItem[] L, System.Web.UI.WebControls.SortDirection SortDirection, string SortField)
        {
            //ListWhere w = new ListWhere();
            //w.SortCondition.fnOrderBy = SortFunctions.fOrderBy;
            //w.SortCondition.SortField = SortField;
            //w.SortCondition.SortDirection = SortDirection;
            //Array.Sort(L, w.SortCondition);
            //return (SortField == "dtStart" ? L[0].DtStart : L[0].DtFinish);            
            return DateTime.Now;

        }

        /// <summary>
        /// Вернуть текстом - статус контракта
        /// </summary>
        /// <param name="_Contract"></param>
        /// <returns></returns>   
        public  string GetTxtContractStatus()
        {
            throw new Exception ("GetTxtContractStatus не поддерживаю");


            //wsDictionary ws = (wsDictionary)AgencyLib_GlobalConstants.CurrentAgency.WS_FactoryList[WS_FactoryList.wsKey_Dictionary]; ;
            //List<DictionaryItem> l = ws.GetDictionary(AgencyLib_GlobalConstants.Dictionary_ContractType);
            //foreach (DictionaryItem i in l)
            //{
            //    if (i.ID == ContractStatus.ID)
            //        return i.Value.ToString();
            //}
            //return string.Empty;
        }



        ///// <summary>
        ///// Сумма платежей по плану платежей
        ///// </summary>
        ///// <param name="_Contract"></param>
        ///// <returns></returns>
        //public double GetPlanPaymentsSumma()
        //{
        //    if (!(ContractStatus is ContractStatus_Contract))
        //        return 0;

        //    return (ContractStatus as ContractStatus_Contract).PaymentsPlan.Summa;
        //}
        ///// <summary>
        ///// Сумма платежей 
        ///// </summary>
        ///// <param name="_Contract"></param>
        ///// <returns></returns>
        //public  double GetPaymentsSumma()
        //{
        //    if (!(ContractStatus is ContractStatus_Contract))
        //        return 0;

        //    ContractStatus_Contract St = (ContractStatus_Contract)ContractStatus;

        //    if (null == St.Payments)
        //        return 0;

        //    return St.Payments.Summa;
        //}

        ///// <summary>
        ///// Разница между планом платежей и платежами
        ///// </summary>
        ///// <param name="_Contract"></param>
        ///// <returns></returns>
        //public  double GetRests()
        //{
        //    return GetPlanPaymentsSumma() - GetPaymentsSumma();
        //}

        ///// <summary>
        ///// Текущя задолженость 
        ///// сумма по плану до ближайшего платежного дня вычесть 
        ///// сумма платежей до текщего дня    
        ///// </summary>
        ///// <returns></returns>
        //public  double GetCurrentRests()
        //{
        //    ContractStatus St = ContractStatus;

        //    if (!(ContractStatus is ContractStatus_Contract))
        //        return 0;

        //    PaymentsPlanItem p = (ContractStatus as ContractStatus_Contract).PaymentsPlan.GetPrev(DateTime.Now);

        //    double planSumm = 0;
        //    double paymentSumm = 0;
        //    if (p != null)
        //        planSumm = (ContractStatus as ContractStatus_Contract).PaymentsPlan.SummaForDate(p.Date);

        //    if (St is ContractStatus_Contract)
        //        paymentSumm = (St as ContractStatus_Contract).Payments.SummaForDate(DateTime.Now);

        //    return planSumm - paymentSumm;
        //}


        #endregion

        #region ISQL
        public override string SaveProcedure
        {
            get
            {
                return "SaveContract";
            }
        }
        #endregion

        /// <summary>
        /// Пересчитать вес сторон 
        /// </summary>
        public override void Save()
        {

            CalculateSideWeight();
            base.Save();
        }

        /// <summary>
        /// Подсчитать вес сторон
        //TContractStatus .Contract     =0
        //TContractStatus.Reserv        =50
        //TContractStatus .MySelfAdvice =100
        //TContractStatus .Other        =100
        //TContractStatus.Prototype     =150
        
        /// </summary>
        public virtual void CalculateSideWeight()
        {
            int BaseWeight=0;
            switch (this.ContractStatus.TypeID)
            {
                case TContractStatus .Contract :
                        BaseWeight=0;
                            break ;
                    case TContractStatus .Reserv :
                        BaseWeight=50;
                            break ;
                    case TContractStatus .MySelfAdvice :
                        BaseWeight=100;
                            break ;                             
                    case TContractStatus .Prototype :
                        BaseWeight=150;
                            break ;
                case TContractStatus.SocialAdvice :
                            BaseWeight = 100;
                            break;
            }

            foreach (TContractSide i in this.ContractSideItemList)
            {
                i.Weight = BaseWeight - i.AddWeight;
            }


        }
    }

    /// <summary>
    /// Стороны принадлежащие контракту
    /// </summary>
    public class TContractSideItemList : EntityList
    {
        [EntityNonSerialized]
        public  ContractEntity Owner { get; set; } 

        public override void Add(EntitySingle obj)
        {
            (obj as TContractSide).ContractID = Owner.ID;

            base.Add(obj);
        }
        /// <summary>
        /// Установить новый отрезок
        /// </summary>
        /// <param name="SideID">Сторона </param>
        /// <param name="dtStart">Дата начала отрезка</param>
        /// <param name="dtFinish">Дата окончания</param>        
        /// <param name="Price">Цена по которой договорились</param>
        public void SetContractSurfaceItem(   String SideID,
                                              DateTime dtStart,
                                              DateTime dtFinish,                                    
                                              int Price)
        {
            Func<TContractSide> GetContractSide = delegate
            {
                Side s = (Side)SqlTools.GetEntitySingle(SideID);
                TContractSide ni = new TContractSide()
                {
                    Side = s,
                    DtStart = dtStart,
                    DtFinish = dtFinish,
                    Price = s.CurrentPrice
                };

                return ni;
            };

            this.Reset();
            foreach (TContractSide i in this)// Ещем к какому сущ. отрезку можно присоседиться
            {
                if (i.Side .ID == SideID)
                {
                    int CrossType = DateTimeTools.GetCrossPeriod(dtStart, dtFinish, i.DtStart, i.DtFinish);
                    switch (CrossType)
                    {
                        //case 0: // нет пересечений - новый отрезок                                                         

                        //    ContractSurfaceItem ni = new ContractSurfaceItem()-
                        //    {
                        //        SideID = SideID,
                        //        ContractID = ContractID,
                        //        DtStart = dtStart,
                        //        DtFinish = dtFinish
                        //    };
                        //    this.Add(ni);
                        //    return;

                        case 1:// Если X входит в Y 
                            i.DtFinish = dtFinish;
                            i.DtStart = dtStart;
                            return;

                        case 7:// Если Y входит в X 
                            i.DtFinish = dtFinish;
                            i.DtStart = dtStart;
                            return;


                        case 2:// пересечени слева                            
                            i.DtStart = dtStart;
                            return;
                        case 4:// периоды идентичны
                            this.Remove(i.ID);
                            return;

                        case 6: //примыкание справа
                            i.DtStart = dtStart;
                            return;
                        case 3://примыкание слева 
                            i.DtFinish = dtFinish;
                            return;

                        //x Примыкает слева                        
                        case 5:
                            i.DtFinish = dtFinish;
                            return;


                    }

                }
            }

            this.Reset();
            foreach (TContractSide i in this)// Ещем к какому сущ. отрезку можно присоседиться
            {
                if (i.Side.ID == SideID)
                {
                    int CrossType = DateTimeTools.GetCrossPeriod(dtStart, dtFinish, i.DtStart, i.DtFinish);
                    switch (CrossType)
                    {
                        case 0: // нет пересечений - новый отрезок                                                         


                            this.Add(GetContractSide());
                            return;
                    }
                }

            }

            ///Нет отрезков к которым можно присос. - доб. новый
            
            this.Add(GetContractSide());

            

        }
                
    }


    [TagNameInfo(TagName = "ContractStatus")]
    public class TContractStatus : EntitySingle 
    {
        #region Виды контрактов                
        public const string Prototype = "3FE7F9BE-1899-4C25-A6FD-5227A6C88CD8";        
        public const string Contract = "CD3ED073-5730-4E68-A488-B3990A620818";
        public const string Reserv = "BC337E12-1D33-4D4B-AFA5-9FB0774A933C";
        public const string SocialAdvice = "1CE2449A-84F4-45C2-A88F-C90ACBA279F8";
        public const string MySelfAdvice = "91ACAD5E-029D-4156-A047-9D94B88C812B";
        public const string Other = "FBA952B1-B0C7-4F39-A120-EADE151A1359";
        
        #endregion


        public override string ID
        {
            get
            {
                return base.ID;
            }
            set
            {
                base.ID = value;
            }
        }

        [SrchItemInfo(TxtPropertyName = SrchItemInfo.EmptyString)]
        public string TypeID
        {
            get;
            set;
        }

        [SrchItemInfo(TxtPropertyName = "Наменование")]
        public string Name
        {
            get;
            set;
        }

        DateTime _Date = DateTime.Now;
        [SrchItemInfo(TxtPropertyName = "Дата")]
        public DateTime  Date
        {
            get { return _Date; }
            set{_Date =value ;}
        }

        /// <summary>
        /// вернуть  возможный набор статусов
        /// </summary>
        public static List<DictionaryItem> GetFullList()
        {
            List<DictionaryItem> result = new List<DictionaryItem>();
            result.Add(new DictionaryItem() { ParamID = Prototype, Value = "Прототип" });
            result.Add(new DictionaryItem() { ParamID = Reserv, Value = "Бронирование" });
            result.Add(new DictionaryItem() { ParamID = Contract, Value = "Контракт" });
            result.Add(new DictionaryItem() { ParamID =MySelfAdvice , Value = "Самореклама" });
            result.Add(new DictionaryItem() { ParamID = SocialAdvice , Value = "Соц. реклама" });
            result.Add(new DictionaryItem() { ParamID = Other , Value = "Другое" });

            return result;
        }
        public static TContractStatus GetStatus(string ID)
        {
            foreach (DictionaryItem i in GetFullList())
            {
                if( i.ParamID ==ID)
                    return new TContractStatus() { TypeID = i.ParamID, Name = i.Value.ToString() };
            }
            return null;
        }
    }

    [TagNameInfo(TagName = "TContractSide")]
    public class TContractSide : EntitySingle 
    {

        public Side Side { get; set; }

        public string  ContractID { get; set; }

        public DateTime DtStart { get; set; }

        public DateTime DtFinish { get; set; }

        /// <summary>
        /// Цена по которой договорились
        /// </summary>
        public int Price { get; set; }

        public int Summa
        {
            get
            {
                return DateTimeTools.GetDayDiff(DtFinish, DtStart) * Price;
            }
        }

        /// <summary>
        /// Приоритет в очереди (дополнительный вес)
        /// </summary>
        public int AddWeight {get;set;}

        private int _Weight = 0;
        
        public int Weight { get { return _Weight; } set { _Weight = value; } }

        /// <summary>
        /// проверить на предмет нахождения записи в очереди.
        /// прогрузить расписание очереди если номер в очереди >0 true;
        /// 
        /// </summary>
        [EntityNonSerialized ]
        public bool ItemIn_Q
        {
            get 
            {
                SideShedule Shedule= SideShedule.GetSideShedule(Side.ID, DtStart, DtFinish);
                Shedule.Load();
                SurfaceSheduleItem item = (SurfaceSheduleItem)Shedule[ID];
                if (null == item)
                    return false;
                return item.SurfNumber > 0;                
            }

        }
        
    }

    [TagNameInfo(TagName = "TFinanceInfo")]
    public class TFinanceInfo : EntitySingle
    {
        private EntityList _PaymentsPlan = new EntityList();
        public EntityList PaymentsPlan { get { return _PaymentsPlan; } set { _PaymentsPlan = value; } }

        private EntityList _Payables = new EntityList();
        public EntityList Payables { get { return _Payables; } set { _Payables = value; } }

        private int GetSumma(EntityList PaymentsList)
        {
            int result = 0;
            for (int i = 0; i < PaymentsList.Count; i++)
            {
                result = result + (PaymentsList[i] as TPaymentItem).Summa;

            }
            return result ;

        }
        [SrchItemInfo(TxtPropertyName = "Сумма")]
        public int Summa_Plan { get { return GetSumma(_PaymentsPlan); } }
        
        [SrchItemInfo(TxtPropertyName = "Оплачено")]
        public int Summa_Fact { get { return GetSumma(_Payables); } }
        
        [SrchItemInfo(TxtPropertyName = "Баланс")]
        public int Summa_Balance { get { return (Summa_Plan - Summa_Fact); } }

        

    }

    
    /// <summary>
    /// финансовый платеж
    /// </summary>
    [TagNameInfo(TagName = "TPaymentItem")]
    public class TPaymentItem : EntitySingle
    {

        public DateTime _Date = DateTime.Now;
        public DateTime Date { get { return _Date; } set { _Date = value; } }
        
        [DefaultValue(0)]
        public int  Summa { get; set; }
        /// <summary>
        /// C какого счета
        /// </summary>
        public virtual int From { get; set; }
        
        /// <summary>
        ///целевой счет
        /// </summary>
        public virtual int To { get; set; }
    }

    /// <summary>
    /// План взносов по контракту
    /// </summary>
    [TagNameInfo(TagName = "TPaymentItem")]
    public class TContractPaymentItem_Plan : TPaymentItem
    {
        public override int From
        {
            get
            {
                return 3;
            }
        }

        public override int To
        {
            get
            {
                return 4;
            }
        }
    }

    /// <summary>
    /// взнос по контракту
    /// </summary>
    [TagNameInfo(TagName = "TPaymentItem")]
    public class TContractPaymentItem_Payables : TPaymentItem
    {
        public override int From
        {
            get
            {
                return 4;
            }
        }

        public override int To
        {
            get
            {
                return 5;
            }
        }
    }


  
}
